package com.treeroot.stack;

import org.jetbrains.annotations.NotNull;

/**
 * 栈实现的计算器
 */
public class StackCalculator {

    /**
     * 计算器类
     * @param express 需要计算的表达式
     */
    public void calculator(@NotNull String express) {
        // 创建两个栈，数栈，一个符号栈
        ArrayStack numStack = new ArrayStack(10);
        ArrayStack operaStack = new ArrayStack(10);
        // 定义需要的相关变量
        //1. 用于扫描的索引
        int index = 0;
        //2.将每次扫描得到的char保存到ch
        char ch;
        //3. 用于存放运算结果
        int num1;
        int num2;
        //4.操作符
        int opera;
        //5.最后结果
        int res;
        // 6. 用于处理多位数的变量
        StringBuilder keepNum = new StringBuilder();
        //7.开始while扫描得到expression的每一个字符
        while (true) {
            // 从字符串中获取字符
            ch = express.charAt(index);
            // 判断字符类型
            if (operaStack.isOpera(ch)) { // 当前字符是运算符
                if (operaStack.isEmpty()) { // 操作符栈为空，直接入栈
                    operaStack.push(ch);
                } else {
                    // 如果当前优先级 <= 栈顶元素优先级，出栈进行计算
                    if (operaStack.priority(ch) <= operaStack.priority(operaStack.peek())) {
                        num1 = numStack.pop(); // 弹出数栈栈顶元素作为被减数
                        num2 = numStack.pop(); // 弹出数栈栈顶元素作为减数
                        opera = operaStack.pop(); // 弹出操作符栈顶元素作为运算符
                        res = numStack.cal(num1, num2, opera); // 将减数和被减数传进去进行计算
                        numStack.push(res); // 运算结果入数栈
                        operaStack.push(ch); // 当前运算符入操作符栈
                    } else { // 操作符优先级 > 栈顶元素优先级，直接入栈
                        operaStack.push(ch);
                    }
                }
            } else { // 当前字符是数字
                keepNum.append(ch); // 处理多位数
                // 如果当前不是数字或者已经是表达式的最后一位，就将keepNum中的数字入数栈，并清空keepNum变量
                if (index == express.length() - 1 || operaStack.isOpera(express.charAt(index + 1))) {
                    numStack.push(Integer.parseInt(keepNum.toString()));
                    keepNum = new StringBuilder();
                }
            }
            index++; // 指针后移
            // 扫描完整个字符串后跳出循环
            if (index >= express.length()) {
                break;
            }
        }
        // 当操作符栈不为空时，继续计算
        while (!operaStack.isEmpty()) {
            num1 = numStack.pop();
            num2 = numStack.pop();
            opera = operaStack.pop();
            res = numStack.cal(num1, num2, opera); // 将减数和被减数传进去进行计算
            numStack.push(res); // 运算结果入数栈
        }
        // 输出结果
        System.out.println("表达式" + express + "的结果是" + numStack.pop());

    }

    public static void main(String[] args) {
      new StackCalculator().calculator("70*20-4");
    }
}
